import os
import shutil
import tempfile
import logging
from pathlib import Path
import PyInstaller.__main__
from utils.logger import get_logger
from config.settings import settings

logger = get_logger()

# 配置PyInstaller日志级别,减少控制台输出
logging.getLogger('PyInstaller').setLevel(logging.WARNING)

class Packager:
    """
    打包核心类
    """
    def __init__(self):
        self.icon_path = None
        self.temp_dir = None
        self.package_path = None
        
        # 使用配置的临时目录
        self.base_temp_dir = settings.temp_dir
        self._ensure_temp_dir()
        
    def _ensure_temp_dir(self):
        """
        确保临时文件夹存在
        """
        try:
            # 如果文件夹不存在则创建
            if not self.base_temp_dir.exists():
                logger.info('创建基础临时目录')
                self.base_temp_dir.mkdir(parents=True)
        except Exception as e:
            logger.error(f'处理临时目录时出错: {str(e)}')
            raise
        
    def set_icon(self, icon_path):
        """设置图标路径"""
        self.icon_path = icon_path
        
    def package(self, python_file, is_single_file, show_console=True):
        """
        执行打包操作
        
        Args:
            python_file (str): Python文件路径
            is_single_file (bool): 是否打包为单个文件
            show_console (bool): 是否显示控制台窗口
        """
        logger.info('开始打包...')
        
        try:
            # 确保临时目录状态正确
            self._ensure_temp_dir()
            
            # 创建新的临时目录
            self.cleanup()  # 清理之前的临时目录
            self.temp_dir = tempfile.mkdtemp(dir=str(self.base_temp_dir))
            logger.info(f'创建临时目录: {self.temp_dir}')
            
            args = [
                python_file,
                '--distpath', os.path.join(self.temp_dir, 'dist'),
                '--workpath', os.path.join(self.temp_dir, 'build'),
                '--specpath', self.temp_dir,
                '--clean',  # 清理临时文件
            ]
            
            if not show_console:
                args.append('--noconsole')  # 添加这个选项来隐藏控制台窗口
            
            if is_single_file:
                args.append('--onefile')
            else:
                args.append('--onedir')
                
            if self.icon_path:
                args.extend(['--icon', self.icon_path])
                
            PyInstaller.__main__.run(args)
            
            # 记录打包后的文件路径
            self.package_path = os.path.join(self.temp_dir, 'dist')
            if not os.path.exists(self.package_path):
                raise Exception('打包失败：未生成目标文件')
                
            logger.info(f'打包文件已保存到临时目录: {self.package_path}')
            
        except Exception as e:
            logger.error(f'PyInstaller打包失败: {str(e)}')
            self.cleanup()
            raise
            
    def save_package(self, output_dir):
        """
        保存打包后的文件到指定目录
        
        Args:
            output_dir (str): 输出目录
        """
        try:
            if not self.package_path or not os.path.exists(self.package_path):
                raise Exception('没有找到打包后的文件，请重新打包')
                
            # 确保输出目录存在
            os.makedirs(output_dir, exist_ok=True)
            
            # 复制打包后的文件到输出目录
            dist_path = self.package_path
            items = os.listdir(dist_path)
            
            if not items:
                raise Exception('打包目录为空')
                
            for item in items:
                src = os.path.join(dist_path, item)
                dst = os.path.join(output_dir, item)
                
                # 如果目标位置已存在，先删除
                if os.path.exists(dst):
                    if os.path.isdir(dst):
                        shutil.rmtree(dst)
                    else:
                        os.remove(dst)
                
                # 复制文件或目录
                if os.path.isdir(src):
                    shutil.copytree(src, dst)
                else:
                    shutil.copy2(src, dst)
                    
            logger.info(f'文件已成功保存到: {output_dir}')
            
        except Exception as e:
            logger.error(f'保存文件失败: {str(e)}')
            raise
        finally:
            self.cleanup()
            
    def cleanup(self):
        """清理临时文件"""
        if self.temp_dir and os.path.exists(self.temp_dir):
            try:
                shutil.rmtree(self.temp_dir)
                logger.info(f'清理临时目录: {self.temp_dir}')
            except Exception as e:
                logger.error(f'清理临时目录失败: {str(e)}')
            finally:
                self.temp_dir = None
                self.package_path = None
                
    def __del__(self):
        """析构函数，确保清理所有临时文件"""
        self.cleanup()
        # 清理基础临时目录（如果为空）
        try:
            if self.base_temp_dir.exists() and not os.listdir(str(self.base_temp_dir)):
                self.base_temp_dir.rmdir()
        except Exception:
            pass 